<?php

use common\service\UserService;
use support\ErrorCode;
use support\Pinyin;
use teamones\Request;
use think\module\Module;

if (!function_exists('check_empty')) {
    /**
     * 自动验证,检测是否为空
     * @param string
     * @return bool
     */
    function check_empty($string)
    {
        if (empty($string)) {
            return false;
        } else {
            return true;
        }
    }
}

if (!function_exists('check_token_time')) {
    /**
     * 验证过期时间
     * @param $tokenTime
     * @return bool
     */
    function check_token_time($tokenTime)
    {
        if (!isset($tokenTime)) {
            return true;
        }
        $expireTime = $tokenTime + C('token_expire_time');
        return time() - $expireTime > 0 ? true : false;
    }
}

if (!function_exists('generate_api_token')) {
    /**
     * 生成api token
     * @param $userId
     * @param $tokenTime
     * @return String
     */
    function generate_api_token($userId, $tokenTime)
    {
        $tokenData = [
            "user_id" => $userId,
            "token_time" => $tokenTime
        ];
        return _encrypt(json_encode($tokenData));
    }
}

if (!function_exists('array_to_string')) {
    /**
     * 数组转字符串
     * @param $val
     * @param string $glue
     * @return string
     */
    function array_to_string($val, $glue = ',')
    {
        if (is_array($val)) {
            return join($glue, $val);
        }
        return $val;
    }
}


if (!function_exists('fill_created_by')) {
    /**
     * 填充当前用户id
     * @return int
     */
    function fill_created_by()
    {
        return \request()->getUserId();
    }
}


if (!function_exists('fill_current_user_union_id')) {
    /**
     * 填充当前用户全局 union id
     * @return mixed
     */
    function fill_current_user_union_id()
    {
        return \request()->getUnionUserId();
    }
}


if (!function_exists('generate_code')) {
    /**
     * 生成编码
     * @param $nameString
     * @param string $delimiter
     * @return string
     */
    function generate_code($nameString, $delimiter = "")
    {

        // 如果name中包含下划线"_" 就切割进行生成
        if (strstr($nameString, '_') !== false) {
            $names = explode('_', $nameString);
            $names = array_map(function ($name) use ($delimiter) {
                $pinyin = Pinyin::getInstance();
                return $pinyin->permalink($name, $delimiter);
            }, $names);
            return implode('_', $names);
        }

        $pinyin = Pinyin::getInstance();
        return $pinyin->permalink($nameString, $delimiter);
    }
}

if (!function_exists('generate_abbr')) {
    /**
     * 生成中文首拼的字符串,保留字母
     * @param string $string
     * @return string
     */
    function generate_abbr(string $string)
    {
        $chinese = ['\p{Han}', '\p{Z}', '\p{M}'];
        $allowRegex = [...$chinese, 'a-zA-Z'];
        return preg_replace_callback(sprintf('~[%s]~u', implode($chinese)), function ($m) {
            return strtoupper(Pinyin::getInstance()->abbr($m[0]));
        }, preg_replace(sprintf('~[^%s]~u', implode($allowRegex)), '', $string));
    }
}

if (!function_exists('generate_asset_code')) {
    /**
     * 生成资产编码
     * @param string $nameString
     * @param int $randomStrLength
     * @return string
     * @throws Exception
     */
    function generate_asset_code(string $nameString, int $randomStrLength = 6)
    {
        $randomStr = get_random_str($randomStrLength);
        return generate_abbr($nameString) . '_' . strtoupper($randomStr);
    }
}

if (!function_exists('auto_fill_code')) {
    /**
     * 自动填充编码
     * @param array $data
     * @param string $field
     * @return bool|string
     * @throws Exception
     */
    function auto_fill_code($data = [], $field = '')
    {
        if (!array_key_exists($field, $data)) {
            if (array_key_exists('name', $data)) {
                return generate_code($data['name'], "");
            } else {
                return false;
            }
        } else {
            return to_under_score($data[$field]);
        }
    }
}

if (!function_exists('auto_fill_not_null_code')) {
    /**
     * 自动填充编码
     * @param array $data
     * @param string $field
     * @return bool|mixed|string
     * @throws Exception
     */
    function auto_fill_not_null_code($data = [], $field = '')
    {
        if (!isset($data[$field]) || empty($data[$field])) {
            if (array_key_exists('name', $data)) {
                return generate_code($data['name'], "");
            } else {
                return false;
            }
        } else {
            return $data[$field];
        }
    }
}


if (!function_exists('auto_fill_project_id')) {
    /**
     * 自动填充项目ID
     * @param array $data
     * @param string $field
     * @return mixed
     */
    function auto_fill_project_id($data = [], $field = '')
    {
        if (!array_key_exists($field, $data)) {
            return \request()->getProjectId();
        }

        return $data[$field];
    }
}

if (!function_exists('auto_fill_default_id')) {
    /**
     * 自动填充默认ID
     * @param array $data
     * @param string $field
     * @return mixed
     */
    function auto_fill_default_id($data = [], $field = '')
    {
        if (!array_key_exists($field, $data)) {
            return 0;
        }

        return $data[$field];
    }
}


if (!function_exists('auto_fill_tenant_id')) {
    /**
     * 自动填充租户ID
     * @return int
     */
    function auto_fill_tenant_id()
    {
        return \request()->getTenantId();
    }
}


if (!function_exists('string_is_component')) {
    /**
     * 判断字符串是否为纯字母
     * @param $str
     * @return bool
     */
    function string_is_component($str)
    {
        if (preg_match("/^[A-Za-z]/", $str)) {
            return true;
        } else {
            return false;
        }
    }
}

if (!function_exists('array_to_json')) {
    /**
     * 把数组转换成Json
     * @param $arr
     * @return string
     */
    function array_to_json($arr)
    {
        if (is_array($arr)) {
            $res_arr = json_encode($arr);
        } else {
            $res_arr = $arr;
        }
        return $res_arr;
    }
}

if (!function_exists('is_json')) {
    /**
     * 检测元素是否为json
     * @param $string
     * @return bool
     */
    function is_json($string)
    {
        json_decode($string);
        return (json_last_error() == JSON_ERROR_NONE);
    }
}

if (!function_exists('check_array_unique')) {
    /**
     * 判断数组是否为有重复元素
     * @param $arr
     * @return bool
     */
    function check_array_unique($arr)
    {
        if (count($arr) != count(array_unique($arr))) {
            return false;
        } else {
            return true;
        }
    }
}

if (!function_exists('check_array_dimension')) {
    /**
     * 判断数组为一维数组还是二维数组
     * @param $arr
     * @return bool
     */
    function check_array_dimension($arr)
    {
        if (count($arr) == count($arr, 1)) {
            return false;
        } else {
            return true;
        }
    }
}

if (!function_exists('check_is_relation_create')) {
    /**
     * 判断数组为一维数组还是二维数组
     * @param $arr
     * @return bool
     */
    function check_is_relation_create($arr)
    {
        $notRelationFields = ['template_content', 'config', 'json', 'node_config', 'param', 'start_man', 'step_category_dependency', 'participant_man', 'job_option', 'after_option', 'step_category_config', 'invoke_department_man', 'step_workflow_config', 'version_file_review', 'version_file_work', 'version_file_publish']; // 不需要创建关联表的字段
        foreach ($arr as $key => $data) {
            if (is_array($data) && check_array_dimension($data) && !in_array($key, $notRelationFields)) {
                return true;
            }
        }

        return false;
    }
}

if (!function_exists('check_cc_number')) {
    /**
     * 自动验证,检测cc是否超过6个
     * @param string $cc
     * @return bool
     */
    function check_cc_number($cc)
    {
        $cc_arr = explode(',', $cc);
        if (count($cc_arr) > 6) {
            return false;
        } else {
            return true;
        }
    }
}

if (!function_exists('create_pass')) {
    /**
     * 加密密码
     * @param string $password
     * @return bool|string
     */
    function create_pass($password = "")
    {
        if (!empty($password)) {
            $options = [
                'cost' => 8,
            ];
            return password_hash($password, PASSWORD_BCRYPT, $options);
        } else {
            return '';
        }
    }
}

if (!function_exists('check_pass')) {
    /**
     * 验证密码
     * @param $password
     * @param $encryptionPassword
     * @return bool
     */
    function check_pass($password, $encryptionPassword)
    {
        return password_verify($password, $encryptionPassword);

    }
}

if (!function_exists('fill_default_pass')) {
    /**
     * 填充默认密码
     * @param string $pass
     * @return mixed|string
     */
    function fill_default_pass($pass = "")
    {
        // 获取默认密码
        if (empty($pass)) {
            $userService = UserService::getInstance();
            $pass = $userService->getUserDefaultPassword();
        }
        return $pass;
    }
}

if (!function_exists('check_login_is_email')) {
    /**
     * 判断登录名是否是邮箱地址
     * @param $login
     * @return bool
     */
    function check_login_is_email($login)
    {
        $checkmail = '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/';
        if (preg_match($checkmail, $login)) {
            return true;
        } else {
            return false;
        }
    }
}

if (!function_exists('_encrypt')) {
    /**
     * 简单对称加密算法之加密
     * @param String $string 需要加密的字串
     * @param Bool $isarry 是否是数组
     * @param String $skey 加密EKY
     * @return String
     */
    function _encrypt($string = '', $isarry = false, $skey = null)
    {
        $skey = $skey === null ? C('COOKIE_KEY') : $skey;
        $string = $isarry === true ? json_encode($string) : $string;
        $strArr = str_split(base64_encode($string));
        $strCount = count($strArr);
        foreach (str_split($skey) as $key => $value) {
            $key < $strCount && $strArr[$key] .= $value;
        }
        return str_replace(array('=', '+', '/'), array('O0O0O', 'o000o', 'oo00o'), join('', $strArr));
    }
}

if (!function_exists('_decrypt')) {
    /**
     * 简单对称加密算法之解密
     * @param String $string 需要解密的字串
     * @param Bool $isarry 是否是数组
     * @param String $skey 解密KEY
     * @return String
     */
    function _decrypt($string = '', $isarry = false, $skey = null)
    {
        try {
            $skey = $skey === null ? C('COOKIE_KEY') : $skey;
            $strArr = str_split(str_replace(array('O0O0O', 'o000o', 'oo00o'), array('=', '+', '/'), $string), 2);
            $strCount = count($strArr);
            foreach (str_split($skey) as $key => $value) {
                //$key <= $strCount && isset($strArr[$key]) && $strArr[$key][1] === $value && $strArr[$key] = $strArr[$key][0];
                if ($key <= $strCount && array_key_exists($key, $strArr)) {
                    if (strlen($strArr[$key]) === 2 && $strArr[$key][1] === $value) {
                        $strArr[$key] = $strArr[$key][0];
                    } else {
                        throw new \common\exception\LogicException("error", ErrorCode::DECRYPTION_FAILED);
                    }
                } else {
                    throw new \common\exception\LogicException("error", ErrorCode::DECRYPTION_FAILED);
                }

            }
            $decode = base64_decode(join('', $strArr));
            $decode = $isarry === true ? json_decode($decode, true) : $decode;
        } catch (Exception $e) {
            $decode = [];
        }
        return $decode;
    }
}

if (!function_exists('get_lang_type')) {
    /**
     * 返回语言包类型
     * @param string $lang
     * @return string
     */
    function get_lang_type($lang)
    {
        switch ($lang) {
            case 'zh-cn':
                $lang_type = 'zh-cn';
                break;
            case 'en-us':
                $lang_type = 'en-us';
                break;
            default:
                $lang_type = 'en-us';
        }
        return $lang_type;
    }
}

if (!function_exists('is_today')) {
    /**
     * 判断日期是否为今天
     * @param $date
     * @return int
     */
    function is_today($date)
    {
        $c_date = date('Y-m-d', $date);
        $today = date('Y-m-d');
        if ($c_date == $today) {
            return 1;
        } else {
            return 0;
        }
    }
}

if (!function_exists('is_hurry_date')) {
    /**
     * 判断任务截至日期是否在捉急
     * @param $date
     * @param $days
     * @return string
     */
    function is_hurry_date($date, $days)
    {
        $section = $days * 86400;
        $now = time();
        $cnow = $date + $section;
        if ($cnow < $now) {
            $isHurry = 'hurry';
        } else {
            $isHurry = 'nohurry';
        }
        return $isHurry;
    }
}

if (!function_exists('remove_file_suffix')) {
    /**
     * 去除文件名后缀
     * @param $filename
     * @return string
     */
    function remove_file_suffix($filename)
    {
        $FileExt = substr(strrchr($filename, '.'), 1);
        $newName = basename($filename, "." . $FileExt);
        return $newName;
    }
}

if (!function_exists('create_base64_Img')) {
    /**
     * base64图片保存到临时路径
     * @param $img
     * @param $tpye
     * @return mixed
     * @throws Exception
     */
    function create_base64_Img($img, $tpye)
    {
        $fileNameRandom = string_random(8) . time(); //产生一个随机文件名
        $resData = fill_imgfile_content($img, $tpye, $fileNameRandom);
        return $resData["full_path"];
    }
}

if (!function_exists('create_temp_img')) {
    /**
     * 创建临时图片文件
     * @param $img
     * @param $tpye
     * @return array
     * @throws Exception
     */
    function create_temp_img($img, $tpye)
    {
        $baseName = string_random(8) . time();
        $fileNameRandom = $baseName . "_temp"; //产生一个随机文件名
        $resData = fill_imgfile_content($img, $tpye, $fileNameRandom);
        $resData["base_name"] = $baseName;
        return $resData;
    }
}

if (!function_exists('fill_imgfile_content')) {
    /**
     * 保存图片Base64图片
     * @param $img
     * @param $tpye
     * @param $fileNameRandom
     * @return array
     */
    function fill_imgfile_content($img, $tpye, $fileNameRandom)
    {
        //图片解码
        $base64Body = substr(strstr($img, ','), 1);
        $data = base64_decode($base64Body);
        //生成上传路径
        $imageSERVER = $_SERVER['DOCUMENT_ROOT'];
        $fileName = $imageSERVER . __ROOT__ . "/uploads/temp/" . $fileNameRandom . '.' . $tpye;
        file_put_contents($fileName, $data);
        $response = array(
            "full_path" => $fileName,
            "file_name" => $fileNameRandom,
            "ext" => $tpye
        );
        return $response;
    }
}

if (!function_exists('transcode_to_base64_Img')) {
    /**
     * 读取图片文件，转换成base64编码格式
     * @param $image
     * @return string
     */
    function transcode_to_base64_Img($image)
    {
        $IMG_SERVER = $_SERVER['DOCUMENT_ROOT'];
        $image_file = $IMG_SERVER . '/' . $image;
        $image_info = getimagesize($image_file);
        $base64_image = "data:{$image_info['mime']};base64," . chunk_split(base64_encode(file_get_contents($image_file)));
        return $base64_image;
    }
}

if (!function_exists('string_random')) {
    /**
     * 随机字符串加数字
     * @param $length
     * @return string
     * @throws Exception
     */
    function string_random($length)
    {
        $int = $length / 2;
        $bytes = random_bytes($int);
        $string = bin2hex($bytes);
        return $string;
    }
}

if (!function_exists('create_sms_code')) {
    /**
     * 生成短信验证码
     * @param int $length
     * @return int
     */
    function create_sms_code($length = 6)
    {
        $min = pow(10, ($length - 1));
        $max = pow(10, $length) - 1;
        return rand($min, $max);
    }
}

if (!function_exists('random_hash_keys')) {
    /**
     * secret key 密钥生成 32位
     * @param $string
     * @param $created
     * @return string
     * @throws Exception
     */
    function random_hash_keys($string, $created)
    {
        $data = $string . $created . string_random(10);
        $key = hash('md5', $data);
        return $key;
    }
}

if (!function_exists('string_wordwrap')) {
    /**
     * 按照指定长度对字符串进行折行处理
     * @param $string
     * @param $Length
     * @return string
     */
    function string_wordwrap($string, $Length)
    {
        $Arry = explode(" ", $string);
        $NewString = '';
        foreach ($Arry as $Line) {
            if (strlen($Line) > $Length)
                $NewString .= wordwrap($Line, $Length, " ", true);
            else
                $NewString .= " " . $Line;
        }
        return $NewString;
    }
}

if (!function_exists('int_to_string')) {
    /**
     * select返回的数组进行整数映射转换
     * @param $data
     * @param array $map
     * @return array
     */
    function int_to_string(&$data, $map = array('status' => array(1 => '正常', -1 => '删除', 0 => '禁用', 2 => '未审核', 3 => '草稿')))
    {
        if ($data === false || $data === null) {
            return $data;
        }
        $data = (array)$data;
        foreach ($data as $key => $row) {
            foreach ($map as $col => $pair) {
                if (isset($row[$col]) && isset($pair[$row[$col]])) {
                    $data[$key][$col . '_text'] = $pair[$row[$col]];
                }
            }
        }
        return $data;
    }
}

if (!function_exists('list_sort_by')) {
    /**
     * 对查询结果集进行排序，asc正向排序 desc逆向排序 nat自然排序
     * @access public
     * @param array $list 查询结果
     * @param string $field 排序的字段名
     * @param array $sortby 排序类型
     * @return array|bool
     */
    function list_sort_by($list, $field, $sortby = 'asc')
    {
        if (is_array($list)) {
            $refer = $resultSet = array();
            foreach ($list as $i => $data)
                $refer[$i] = &$data[$field];
            switch ($sortby) {
                case 'asc': // 正向排序
                    asort($refer);
                    break;
                case 'desc':// 逆向排序
                    arsort($refer);
                    break;
                case 'nat': // 自然排序
                    natcasesort($refer);
                    break;
            }
            foreach ($refer as $key => $val)
                $resultSet[] = &$list[$key];
            return $resultSet;
        }
        return false;
    }
}

if (!function_exists('multiple_sort_by')) {
    /**
     * 多列排序  ['列1'=>'asc','列2'=>'desc']
     * @param $data
     * @param $sortFields
     */
    function multiple_sort_by(&$data, $sortFields)
    {
        $sortMap = [];
        foreach ($data as $dataItem) {
            foreach ($sortFields as $sortKey => $sortField) {
                $sortMap[$sortKey][] = $dataItem[$sortKey];
            }
        }

        $result = [];
        foreach ($sortFields as $sortKey => $sortField) {
            $result[] = $sortMap[$sortKey];
            switch ($sortField) {
                case 'asc': // 正向排序
                    $result[] = SORT_ASC;
                    break;
                case 'desc':// 逆向排序
                    $result[] = SORT_DESC;
                    break;
                case 'nat': // 自然排序
                    $result[] = SORT_NATURAL;
                    break;
            }
        }
        $result[] = &$data;
        array_multisort(...$result);
    }
}

if (!function_exists('convert_select_data')) {
    /**
     * 转换二维数组为一维数组
     * @param $field
     * @param $array
     * @param string $indexKey
     * @return array
     */
    function convert_select_data($field, $array, $indexKey = '')
    {
        $convertData = [];
        if (!empty($indexKey)) {
            $useIndexKey = $indexKey;
        } else {
            $useIndexKey = $field;
        }
        foreach ($array as $item) {
            array_push($convertData, $item[$useIndexKey]);
        }
        return $convertData;
    }
}

if (!function_exists('unique_arr')) {
    /**
     * 去除数组重复
     * @param $filterData
     * @return array
     */
    function unique_arr($filterData)
    {
        $filterData = array_flip(array_flip($filterData));
        $newFilterData = array();
        foreach ($filterData as $k => $v) {
            if ($v == '') {
                unset($filterData[$k]);
            }
            $newFilterData[] = $filterData[$k];
        }
        return $newFilterData;
    }
}

if (!function_exists('batch_handle_data')) {
    /**
     * 批量更新数据预处理
     * @param $upData
     * @return array
     */
    function batch_handle_data($upData)
    {
        $innateData = array();
        $customData = array();
        foreach ($upData as $value) {
            switch ($value["part"]) {
                case "innate":
                    $innateData[$value["field"]] = $value["value"];
                    break;
                case "custom":
                    switch ($value["edit"]) {
                        case 20://datebox
                            $pval = strtotime($value["value"]);
                            break;
                        default:
                            $pval = $value["value"];
                            break;
                    }
                    $temp = array(
                        "fid" => $value["fid"],
                        "alias" => $value["field"],
                        "value" => $pval,
                        "edit" => $value["edit"],
                        "pos" => "batch",
                    );
                    array_push($customData, $temp);
                    break;
            }
        }
        $response = array(
            "innate" => $innateData,
            "custom" => $customData,
        );
        return $response;
    }
}

if (!function_exists('intval_string')) {
    /**
     * 强制转换字符串为整型, 对数字或数字字符串无效
     * @param mixed $value
     */
    function intval_string(&$value)
    {
        if (!is_numeric($value)) {
            $value = intval($value);
        }
    }
}

if (!function_exists('create_uuid')) {
    /**
     * 生成uuid
     * @return mixed
     * @throws Exception
     */
    function create_uuid()
    {
        if (function_exists("uuid_create")) {
            return uuid_create();
        } else {
            return Webpatser\Uuid\Uuid::generate()->string;
        }
    }
}

if (!function_exists('fill_text_default_val')) {
    /**
     * 填充mysql文本类型字段默认值
     * @param $value
     * @return string
     */
    function fill_text_default_val($value = '')
    {
        if (!isset($value)) {
            return '';
        }
        return $value;
    }
}

if (!function_exists('version_format')) {
    /**
     * 格式化版本号
     * @param $version
     * @return string
     */
    function version_format($version)
    {
        if (!strpos($version, 'V')) {
            return "V" . sprintf("%03d", $version);
        } else {
            return $version;
        }
    }
}

if (!function_exists('get_date_group_md5')) {
    /**
     * 获取时间md5
     * @param $date
     * @param bool $is_full
     * @return string
     */
    function get_date_group_md5($date, $is_full = false)
    {
        if ($is_full) {
            return md5($date);
        } else {
            $dateFormat = date('Y-m-d', strtotime($date));
            return md5($dateFormat);
        }
    }
}

if (!function_exists('string_initial_letter')) {
    /**
     * 下划线单个字母大写返回分隔符自定义
     * @param $string
     * @param string $prefix
     * @return string
     */
    function string_initial_letter($string, $prefix = '')
    {
        if (strpos($string, '_')) {
            $stringArray = explode('_', $string);
            $doneString = [];
            foreach ($stringArray as $item) {
                array_push($doneString, ucfirst($item));
            }
            return join($prefix, $doneString);
        } else {
            return ucfirst($string);
        }
    }
}

if (!function_exists('camelize')) {
    /**
     *  下划线转驼峰
     * 思路:
     * step1.原字符串转小写,原字符串中的分隔符用空格替换,在字符串开头加上分隔符
     * step2.将字符串中每个单词的首字母转换为大写,再去空格,去字符串首部附加的分隔符.
     * @param $unCamelizeWords
     * @param string $separator
     * @return string
     */
    function camelize($unCamelizeWords, $separator = '_')
    {
        $unCamelizeWords = $separator . str_replace($separator, " ", strtolower($unCamelizeWords));
        return str_replace(" ", "", ucwords(ltrim($unCamelizeWords, $separator)));
    }
}

if (!function_exists('get_table_name')) {
    /**
     * 获取table名称
     * @param $code
     * @return string
     */
    function get_table_name($code)
    {
        return ucwords(camelize($code));
    }
}

if (!function_exists('create_directory')) {
    /**
     * 判断目录是否存在,不存在则创建
     * @param $path
     * @param $mode
     * @return string
     */
    function create_directory($path, $mode = 0777)
    {
        if (is_dir($path)) {
            //判断目录存在否，存在不创建
            return "目录'" . $path . "'已经存在";
            //已经存在则输入路径
        } else { //不存在则创建目录
            $re = mkdir($path, $mode, true);
            //第三个参数为true即可以创建多极目录
            if ($re) {
                return "目录创建成功";
            } else {
                return "目录创建失败";
            }
        }
    }
}

if (!function_exists('delete_directory')) {
    /**
     * 删除指定目录下所有文件及其本身
     * @param $dir
     * @return bool
     */
    function delete_directory($dir)
    {
        if (!file_exists($dir)) {
            return true;
        }
        if (!is_dir($dir)) {
            return unlink($dir);
        }
        foreach (scandir($dir) as $item) {
            if ($item == '.' || $item == '..') {
                continue;
            }
            if (!delete_directory($dir . DIRECTORY_SEPARATOR . $item)) {
                return false;
            }
        }
        return rmdir($dir);
    }
}

if (!function_exists('empty_folder')) {
    /**
     * 删除指定目录下的文件，不删除目录文件夹
     * @param $dir
     */
    function empty_folder($dir)
    {
        //删除目录下的文件：
        $dh = opendir($dir);
        while ($file = readdir($dh)) {
            if ($file != "." && $file != "..") {
                $fullpath = $dir . "/" . $file;
                if (!is_dir($fullpath)) {
                    unlink($fullpath);
                } else {
                    empty_folder($fullpath);
                }
            }
        }
        closedir($dh);
    }
}

if (!function_exists('bath_empty_file_content')) {
    /**
     * 清空指定目录下的文件内容，不删除目录文件夹
     * @param $dir
     */
    function bath_empty_file_content($dir)
    {
        $dh = opendir($dir);
        while ($file = readdir($dh)) {
            if ($file != "." && $file != "..") {
                $fullPath = $dir . "/" . $file;
                if (!is_dir($fullPath)) {
                    file_put_contents($fullPath, "");
                } else {
                    bath_empty_file_content($fullPath);
                }
            }
        }
        closedir($dh);
    }
}

if (!function_exists('get_directory_size')) {
    /**
     * 文件夹大小
     * @param $dir
     * @return int
     */
    function get_directory_size($dir)
    {
        $handle = opendir($dir);
        if (empty($sizeResult)) {
            $sizeResult = 0;
        }
        while (false !== ($FolderOrFile = readdir($handle))) {
            if ($FolderOrFile != "." && $FolderOrFile != "..") {
                if (is_dir("$dir/$FolderOrFile")) {
                    $sizeResult += get_directory_size("$dir/$FolderOrFile");
                } else {
                    $sizeResult += filesize("$dir/$FolderOrFile");
                }
            }
        }
        closedir($handle);
        return $sizeResult;
    }
}

if (!function_exists('get_week')) {
    /**
     * 获取星期方法
     * @param $time
     * @return string
     */
    function get_week($time)
    {
        $weekArray = array("sun", "mon", "tue", "wed", "thu", "fri", "sat");
        return $weekArray[date('w', $time)];
    }
}

if (!function_exists('date_friendly')) {
    /**
     * 时间友好型提示风格化（即微博中的XXX小时前、昨天等等）
     * 即微博中的 XXX 小时前、昨天等等, 时间超过 $time_limit 后返回按 out_format 的设定风格化时间戳
     * @param string $time_style
     * @param int $timestamp
     * @param int $time_limit
     * @param string $out_format
     * @param array $formats
     * @param int $time_now
     * @return string
     *
     */
    function date_friendly($time_style, $timestamp, $time_limit = 604800, $out_format = 'Y-m-d H:i', $formats = null, $time_now = null)
    {
        if ($time_style == 'N') {
            return date($out_format, $timestamp);
        }

        if (!$timestamp) {
            return false;
        }

        if ($formats == null) {
            $formats = array('YEAR' => '%s years ago',
                'MONTH' => '%s month before',
                'DAY' => '%s days ago',
                'HOUR' => '%s hours ago',
                'MINUTE' => '%s minutes before',
                'SECOND' => '%s ago'
            );
        }

        $time_now = $time_now == null ? time() : $time_now;
        $seconds = $time_now - $timestamp;

        if ($seconds == 0) {
            $seconds = 1;
        }

        if (!$time_limit or $seconds > $time_limit) {
            return date($out_format, $timestamp);
        }

        $minutes = floor($seconds / 60);
        $hours = floor($minutes / 60);
        $days = floor($hours / 24);
        $months = floor($days / 30);
        $years = floor($months / 12);

        if ($years > 0) {
            $diffFormat = 'YEAR';
        } else {
            if ($months > 0) {
                $diffFormat = 'MONTH';
            } else {
                if ($days > 0) {
                    $diffFormat = 'DAY';
                } else {
                    if ($hours > 0) {
                        $diffFormat = 'HOUR';
                    } else {
                        $diffFormat = ($minutes > 0) ? 'MINUTE' : 'SECOND';
                    }
                }
            }
        }

        $dateDiff = null;

        switch ($diffFormat) {
            case 'YEAR' :
                $dateDiff = sprintf($formats[$diffFormat], $years);
                break;
            case 'MONTH' :
                $dateDiff = sprintf($formats[$diffFormat], $months);
                break;
            case 'DAY' :
                $dateDiff = sprintf($formats[$diffFormat], $days);
                break;
            case 'HOUR' :
                $dateDiff = sprintf($formats[$diffFormat], $hours);
                break;
            case 'MINUTE' :
                $dateDiff = sprintf($formats[$diffFormat], $minutes);
                break;
            case 'SECOND' :
                $dateDiff = sprintf($formats[$diffFormat], $seconds);
                break;
        }
        return $dateDiff;
    }
}

if (!function_exists('get_current_week_range')) {
    /**
     * 获取当前时间所在星期的开始时间与结束时间戳
     * @return array
     */
    function get_current_week_range()
    {
        $ret = array();
        $timestamp = mktime(0, 0, 0);
        $w = strftime('%u', $timestamp);
        $ret['sdate'] = $timestamp - ($w - 1) * 86400;
        $ret['edate'] = strtotime('+1 day', $timestamp + (7 - $w) * 86400 - 1);
        return $ret;
    }
}

if (!function_exists('get_current_day_range')) {
    /**
     * 获取当前时间所在天的开始时间与结束时间戳
     * @param $timestamp
     * @return array
     */
    function get_current_day_range($timestamp)
    {
        $ret = array();
        $ret['sdate'] = strtotime(date('Y-m-d', $timestamp));
        $ret['edate'] = $ret['sdate'] + 86399;
        return $ret;
    }
}

if (!function_exists('get_current_week_each_day')) {
    /**
     * 获取当前时间所在星期的每天时间戳
     * @return array
     */
    function get_current_week_each_day()
    {
        $ret = array();
        $timestamp = mktime(0, 0, 0);
        $w = strftime('%u', $timestamp);
        $ret['Mon'] = $timestamp - ($w - 1) * 86400;
        $ret['Tue'] = $timestamp - ($w - 2) * 86400;
        $ret['Wed'] = $timestamp - ($w - 3) * 86400;
        $ret['Thu'] = $timestamp - ($w - 4) * 86400;
        $ret['Fri'] = $timestamp - ($w - 5) * 86400;
        $ret['Sta'] = $timestamp - ($w - 6) * 86400;
        $ret['Sun'] = $timestamp - ($w - 7) * 86400;
        $ret['sdate'] = $ret['Mon'];
        $ret['edate'] = strtotime('+1 day', $ret['Sun'] - 1);
        return $ret;
    }
}

if (!function_exists('get_week_time_range')) {
    /**
     * 获取指定日期所在星期的开始时间与结束时间(时间戳)
     * @param $date
     * @return array
     */
    function get_week_time_range($date)
    {
        $ret = array();
        $timestamp = strtotime($date . " 00:00:00");
        $w = strftime('%u', $timestamp);
        $ret['sdate'] = $timestamp - ($w - 1) * 86400;
        $ret['edate'] = $timestamp + (7 - $w) * 86400;
        return $ret;
    }
}

if (!function_exists('get_week_range')) {
    /**
     * 获取指定日期所在星期的开始时间与结束时间
     * @param $date
     * @return array
     */
    function get_week_range($date)
    {
        $ret = array();
        $timestamp = strtotime($date);
        $w = strftime('%u', $timestamp);
        $ret['sdate'] = date('Y-m-d 00:00:00', $timestamp - ($w - 1) * 86400);
        $ret['edate'] = date('Y-m-d 23:59:59', $timestamp + (7 - $w) * 86400);
        return $ret;
    }
}

if (!function_exists('get_month_range')) {
    /**
     * 获取指定日期所在月的开始日期与结束日期
     * @param $date
     * @return array
     */
    function get_month_range($date)
    {
        $ret = array();
        $timestamp = strtotime($date);
        $mdays = date('t', $timestamp);
        $ret['sdate'] = date('Y-m-1 00:00:00', $timestamp);
        $ret['edate'] = date('Y-m-' . $mdays . ' 23:59:59', $timestamp);
        return $ret;
    }
}

if (!function_exists('get_month_time')) {
    /**
     * 获取指定日期所在月的开始日期与结束日期(时间戳)
     * @param $date
     * @return array
     */
    function get_month_time($date)
    {
        $ret = array();
        $timestamp = strtotime($date);
        $mdays = date('t', $timestamp);
        $ret['sdate'] = strtotime(date('Y-m-1 00:00:00', $timestamp));
        $ret['edate'] = strtotime(date('Y-m-' . $mdays . ' 23:59:59', $timestamp));
        return $ret;
    }
}

if (!function_exists('get_month_weeks')) {
    /**
     * 获得一个月有多少周
     * @param $month
     * @return array
     */
    function get_month_weeks($month)
    {
        $weekInfo = array();
        $end_date = date('d', strtotime($month . ' +1 month -1 day'));
        for ($i = 1; $i < $end_date; $i = $i + 7) {
            $w = date('N', strtotime($month . '-' . $i));
            $weekInfo[] = array(date('Y-m-d', strtotime($month . '-' . $i . ' -' . ($w - 1) . ' days')), date('Y-m-d', strtotime($month . '-' . $i . ' +' . (7 - $w) . ' days')));
        }
        return $weekInfo;
    }
}

if (!function_exists('get_interval_month')) {
    /**
     * 获取当前时间之后第N个自然月最后一天的日期(时间戳)
     * @param $time
     * @param $num
     * @return int
     */
    function get_interval_month($time, $num)
    {
        $result_day = "";
        $start = intval(date("m", $time));
        for ($i = 0; $i < $num; $i++) {
            if (($start + $i) > 12) {
                $result_day = date("Y-" . (($start + $i) - 12) . "-01", strtotime("+1 year"));
            } else {
                $result_day = date("Y-" . ($start + $i) . "-01", $time);
            }
            $day = date("t", strtotime($result_day));
            $result_day = date("Y-m-d 23:59:59", (strtotime($result_day) + ($day - 1) * 24 * 3600));
        }
        $result_time = strtotime($result_day) + 1;
        return $result_time;
    }
}

if (!function_exists('get_all_month')) {
    /**
     * 获得某个时间段内，所有的自然月
     * @param array $data
     * @return array
     */
    function get_all_month(array $data)
    {
        $firstDate = $data[0];
        $lastDate = $data[1];
        $start = intval(date("m", strtotime($firstDate)));
        $end = intval(date("m", strtotime($lastDate)));
        $result = array();
        for ($i = $start; $i <= $end; $i++) {
            $firstDay = date("Y-" . $i . "-01", strtotime($firstDate));
            $lastDay = date("Y-m-d", strtotime("$firstDay +1 month -1 day"));
            array_push($result, array('firstday' => $i == $start ? $firstDate : $firstDay, 'lastday' => $i == $end ? $lastDate : $lastDay));
        }
        return $result;
    }
}

if (!function_exists('get_weekend_days')) {
    /**
     * 给定日期之间的周末天数
     * @param $startDate
     * @param $endDate
     * @param bool $isWorkday
     * @return float|int
     */
    function get_weekend_days($startDate, $endDate, $isWorkday = false)
    {
        if (strtotime($startDate) > strtotime($endDate)) {
            list($startDate, $endDate) = array($endDate, $startDate);
        };
        $endAdd = 0;
        $startN = date('N', strtotime($startDate));
        $startReduce = ($startN == 7) ? 1 : 0;
        $endN = date('N', strtotime($endDate));
        in_array($endN, array(6, 7)) && $endAdd = ($endN == 7) ? 2 : 1;
        $allDays = abs(strtotime($endDate) - strtotime($startDate)) / 86400 + 1;
        $weekendDays = floor(($allDays + $startN - 1 - $endN) / 7) * 2 - $startReduce + $endAdd;
        if ($isWorkday) {
            $workdayDays = $allDays - $weekendDays;
            return $workdayDays;
        }
        return $weekendDays;
    }
}

if (!function_exists('get_year_time')) {
    /**
     * 获取指定日期所在年的开始日期与结束日期(时间戳)
     * @param $date
     * @return array
     */
    function get_year_time($date)
    {
        $year = date("Y", strtotime($date));
        $ret = array();
        $ret["sdate"] = strtotime($year . "-01-01 00:00:00");
        $ret["edate"] = strtotime($year . "-12-31 23:59:59") + 1;
        return $ret;
    }
}

if (!function_exists('year_month_list')) {
    /**
     * 一年月份
     * @param $month
     * @return array
     */
    function year_month_list($month)
    {
        switch ($month) {
            case 1:
                return [
                    "id" => 1,
                    "name" => '请选择'
                ];
            default:
                return [
                    "id" => $month,
                    "name" => ($month / 10) . 'month'
                ];
        }
    }
}

if (!function_exists('validate_date_format')) {
    /**
     * 判断是否是合法日期
     * @param $date
     * @param string $format
     * @return bool
     */
    function validate_date_format($date, $format = 'Y-m-d')
    {
        $d = DateTime::createFromFormat($format, $date);
        return $d && $d->format($format) == $date;
    }
}

if (!function_exists('is_timestamp')) {
    /**
     * 判断是不是时间戳
     * @param $timestamp
     * @return bool
     */
    function is_timestamp($timestamp)
    {
        $check = (is_int($timestamp) or is_float($timestamp))
            ? $timestamp
            : (string)(int)$timestamp;
        return ($check === $timestamp)
            and ((int)$timestamp <= PHP_INT_MAX)
            and ((int)$timestamp >= ~PHP_INT_MAX);
    }
}

if (!function_exists('get_progress_color')) {
    /**
     * 获取Progress 颜色
     * @param $progress
     * @return string
     */
    function get_progress_color($progress)
    {
        $color = "";
        switch ($progress) {
            case 'blocked'://Blocked 暂停 #e94310 红色
                $color = 'e94310';
                break;
            case 'not_started'://NotStarted 未开始 #cacaca 灰色
                $color = 'cacaca';
                break;
            case 'in_progress'://InProgress 进行中 #11b0e9 蓝色
                $color = '11b0e9';
                break;
            case 'daily'://Daily 审片  #23ddeb 淡蓝色
                $color = '23ddeb';
                break;
            case 'feedback'://Feedback 反馈  #faad14 橙色
                $color = 'faad14';
                break;
            case 'done'://Done 完成  #afd440 绿色
                $color = 'afd440';
                break;
            case 'hide'://Hide 隐藏  #000000 黑色
                $color = '000000';
                break;
        }
        return $color;
    }
}

if (!function_exists('two_dimension_sort')) {
    /**
     * 二维数组根据键值排序, 排序顺序标志 SORT_DESC 降序；SORT_ASC 升序
     * @param $arr
     * @param $sort
     * @param $v
     * @return mixed
     */
    function two_dimension_sort($arr, $sort, $v)
    {
        if ($sort == "0") {
            $sort = "SORT_ASC";
        } elseif ($sort == "1") {
            $sort = "SORT_DESC";
        }
        foreach ($arr as $uniqid => $row) {
            foreach ($row as $key => $value) {
                $arrsort[$key][$uniqid] = $value;
            }
        }
        if ($sort) {
            array_multisort($arrsort[$v], constant($sort), $arr);
        }
        return $arr;
    }
}

if (!function_exists('get_lang_package')) {
    /**
     * 判断语言包
     * @param $id
     * @return array
     */
    function get_lang_package($id)
    {
        switch ($id) {
            case "zh-cn":
                return [
                    'id' => "zh-cn",
                    'name' => "中文（简体）"
                ];
            case "en-us":
                return [
                    'id' => "en-us",
                    'name' => 'English'
                ];
        }
    }
}

if (!function_exists('get_user_timezone_inter')) {
    /**
     * 获取当前用户所在时差
     * @return int|mixed
     */
    function get_user_timezone_inter()
    {
        return C("default_timezone_custom");
    }
}

if (!function_exists('get_timezone_inter')) {
    /**
     * 获取时区差值
     * @param $id
     * @return int
     */
    function get_timezone_inter($id)
    {
        switch ($id) {
            case "Etc/GMT+12":
                return 0;
            case "Etc/GMT+11":
                return -11;
            case "Etc/GMT+10":
                return -10;
            case "Etc/GMT+9":
                return -9;
            case "Etc/GMT+8":
                return -8;
            case "Etc/GMT+7":
                return -7;
            case "Etc/GMT+6":
                return -6;
            case "Etc/GMT+5":
                return -5;
            case "Etc/GMT+4":
                return -4;
            case "Canada/Newfoundland":
                return -3.3;
            case "Etc/GMT+3":
                return -3;
            case "Etc/GMT+2":
                return -2;
            case "Etc/GMT+1":
                return -1;
            case "Etc/GMT":
                return 0;
            case "Etc/GMT-1":
                return 1;
            case "Etc/GMT-2":
                return 2;
            case "Etc/GMT-3":
                return 3;
            case "Iran":
                return 3.3;
            case "Etc/GMT-4":
                return 4;
            case "Asia/Kabul":
                return 4.3;
            case "Etc/GMT-5":
                return 5;
            case "Asia/Kolkata":
                return 5.3;
            case "Etc/GMT-6":
                return 6;
            case "Etc/GMT-7":
                return 7;
            case "Etc/GMT-8":
            case "PRC":
                return 8;
            case "Etc/GMT-9":
                return 9;
            case "Etc/GMT-10":
                return 10;
            case "Etc/GMT-11":
                return 11;
            case "Etc/GMT-12":
                return 12;
            case "Etc/GMT-13":
                return 13;
            case "Etc/GMT-14":
                return 14;
        }
    }
}

if (!function_exists('get_format_date')) {
    /**
     * string格式化用户使用语言
     * @param $time
     * @param int $type
     * @param bool $isGantt
     * @return false|string
     */
    function get_format_date($time, $type = 0, $isGantt = false)
    {
        if (!empty($time) && is_numeric($time)) {
            $inter = get_user_timezone_inter();

            $timestamp = $time + (3600 * $inter);

            switch ($type) {
                case 0:
                    if ($isGantt) {
                        $date = gmdate("d-m-Y", $timestamp);
                    } else {
                        $date = gmdate("Y-m-d", $timestamp);
                    }
                    break;
                case 2:
                    $date = gmdate("Y-m-d H:i", $timestamp);
                    break;
                case 1:
                default:
                    $date = gmdate("Y-m-d H:i:s", $timestamp);
                    break;
            }

            return $date;
        } else {
            return '';
        }
    }
}

if (!function_exists('get_work_month')) {
    /**
     * @param $month
     * @return int
     */
    function get_work_month($month)
    {
        switch ($month) {
            case 10:
                return $month / 10;
            default:
                return 0;
        }
    }
}

if (!function_exists('transfer_time_data')) {
    /**
     * @param $id
     * @return array
     */
    function transfer_time_data($id)
    {
        $time = time();
        $date = [];
        switch ($id) {
            case "current_week":
                $beginThisWeek = mktime(0, 0, 0, date('m'), date('d') - date('w') + 1, date('Y'));
                $date = ["BETWEEN", [$beginThisWeek, $time]];
                break;
            case "current_month":
                $beginThisMonths = strtotime(date('Y-m-d 0:0:0', mktime(0, 0, 0, date('n'), 1, date('Y'))));
                $date = ["BETWEEN", [$beginThisMonths, $time]];
                break;
            case "within_six_months":
                $beginThisSixMonths = mktime(0, 0, 0, date('m', strtotime("-6 month")), 1, date('Y', strtotime("-6 month")));
                $date = ["BETWEEN", [$beginThisSixMonths, $time]];
                break;
            case "within_a_year":
                $beginThisYear = strtotime(date("Y", time()) . "-1" . "-1");
                $date = ["BETWEEN", [$beginThisYear, $time]];
                break;
            case "a_year_ago":
                $beginThisYear = strtotime(date("Y", time()) . "-1" . "-1");
                $beginYearAgo = strtotime("-1 year");
                $date = ["BETWEEN", [$beginYearAgo, $beginThisYear]];
                break;
        }
        return $date;
    }
}

if (!function_exists('rebuild_url')) {
    /**
     * 重新组装生成url
     * @param $url
     * @param $ext
     * @return string
     */
    function rebuild_url($url, $ext)
    {
        $urlBase = str_replace('.html', '', $url);
        return $urlBase . '/' . $ext . '.html';
    }
}

if (!function_exists('array_group_by')) {
    /**
     * 对二维数组进行分组
     * @param $arr
     * @param $key
     * @return array
     */
    function array_group_by($arr, $key)
    {
        $grouped = [];
        foreach ($arr as $value) {
            $grouped[$value[$key]][] = $value;
        }

        if (func_num_args() > 2) {
            $args = func_get_args();
            foreach ($grouped as $groupKey => $value) {
                $param = array_merge([$value], array_slice($args, 2, func_num_args()));
                $grouped[$groupKey] = call_user_func_array('array_group_by', $param);
            }
        }
        return $grouped;
    }
}

if (!function_exists('array_group_by_columns')) {
    /**
     * 对二维数组进行分组
     * @param array $arr
     * @param array $keys
     * @param string $sep
     * @return array
     */
    function array_group_by_columns(array $arr, array $keys, $sep = '#')
    {
        $grouped = [];

        foreach ($arr as $item) {
            $k = '';
            foreach ($keys as $key) {
                if (isset($item[$key])) {
                    if (is_array($item[$key])) {
                        $s = '';
                    } else {
                        $s = $item[$key];
                    }
                } else {
                    $s = '';
                }
                $k .= $s . $sep;
            }
            $k = trim($k, '#');
            $grouped[$k][] = $item;
        }
        return $grouped;
    }
}

if (!function_exists('array_sort_by')) {
    /**
     * 数组排序
     * @param $arr
     * @param $key
     * @param string $type
     * @param bool $showKey
     * @return array
     */
    function array_sort_by($arr, $key, $type = 'asc', $showKey = true)
    {
        $keyValue = [];
        foreach ($arr as $k => $value) {
            $keyValue[$k] = $value[$key];
        }
        if (strtolower($type) === 'asc') {
            asort($keyValue);
        } else {
            arsort($keyValue);
        }
        reset($keyValue);

        $sortData = [];
        foreach ($keyValue as $k => $value) {
            if ($showKey) {
                $sortData[$k] = $arr[$k];
            } else {
                $sortData[] = $arr[$k];
            }
        }
        return $sortData;
    }
}

if (!function_exists('object_to_array')) {
    /**
     * 对象转数组
     * @param $object
     * @return mixed
     */
    function object_to_array(&$object)
    {
        $object = json_decode(json_encode($object), true);
        return $object;
    }
}

if (!function_exists('check_http_code')) {
    /**
     * 检查url是否可以访问
     * @param $url
     * @return array
     */
    function check_http_code($url)
    {
        $ch = curl_init();
        $timeout = 300; // http请求超时300ms
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $timeout);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if ($httpCode === 200) {
            // 转换成毫秒
            $connectTime = curl_getinfo($ch, CURLINFO_CONNECT_TIME) * 1000;
        } else {
            $connectTime = -1;
        }
        // 关闭cURL资源，并且释放系统资源
        return ["http_code" => $httpCode, "connect_time" => $connectTime];
    }
}

if (!function_exists('download_remote_picture')) {
    /**
     * 下载远程图片
     * @param $fileUrl
     * @param $saveTo
     * @param int $timeout
     * @param string $types
     * @return bool|int
     */
    function download_remote_picture($fileUrl, $saveTo, $timeout = 1000, $types = "'.gif|.jpeg|.jpg.|.png|.bmp'")
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $fileUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_NOSIGNAL, 1);    //注意，毫秒超时一定要设置这个
        curl_setopt($ch, CURLOPT_TIMEOUT_MS, $timeout);
        $fileContent = curl_exec($ch);
        curl_close($ch);
        $downloadedFile = fopen($saveTo, 'w');
        fwrite($downloadedFile, $fileContent);
        fclose($downloadedFile);
        if (file_exists($saveTo)) {
            if ($info = @getimagesize($saveTo)) {
                return true;
            }
            $ext = image_type_to_extension($info['2']);
            return stripos($types, $ext);
        } else {
            return false;
        }
    }
}

if (!function_exists('replace_string_to_specified_value')) {
    /**
     * 替换字符串为指定的值
     * @param $string
     * @param array $beReplaceList 替换列表
     * @return mixed
     */
    function replace_string_to_specified_value($string, array $beReplaceList)
    {
        foreach ($beReplaceList as $key => $value) {
            $string = str_replace($key, $value, $string);
        }
        return $string;
    }
}

if (!function_exists('parser_filter_condition')) {
    /**
     * 替换过滤条件中的方法名
     * @param $val
     * @return string|void
     */
    function parser_filter_condition($val)
    {
        $map = [
            'EQ' => '-eq', // 等于
            'NEQ' => '-neq', // 不等于
            'GT' => '-gt', // 大于
            'EGT' => '-egt', // 大于等于
            'LT' => '-lt', // 小于
            'ELT' => '-elt', // 小于等于
            'LIKE' => '-lk', // 模糊查询（像）
            'NOTLIKE' => '-not-lk', // 模糊查询（不像）
            'BETWEEN' => '-bw', // 在之间
            'NOT BETWEEN' => '-not-bw', // 不在之间
            'IN' => '-in', // 在里面
            'NOT IN' => '-not-in', // 不在里面
            'EXP' => '-exp', // 不在里面
            'FIND_IN_SET' => '-fit', // 列表里存在
        ];
        if (array_key_exists($val, $map)) {
            return $map[$val];
        }
    }
}

if (!function_exists('array_to_dict')) {
    /**
     * 数组转字典
     * @param $array
     * @param $indexKey
     * @param string $valueKey
     * @return array
     */
    function array_to_dict($array, $indexKey, $valueKey = '')
    {
        $dictData = [];
        foreach ($array as $item) {
            $tempValue = !empty($valueKey) ? $item[$valueKey] : $item;
            if (array_key_exists($item[$indexKey], $dictData)) {
                $dictData[$item[$indexKey]][] = $tempValue;
            } else {
                $dictData[$item[$indexKey]] = [$tempValue];
            }
        }
        return $dictData;
    }
}

if (!function_exists('combine_dika')) {
    /**
     * 所有数组的笛卡尔积
     * @param array $inputData
     * @return array
     */
    function combine_dika($inputData = [])
    {
        $data = !empty($inputData) ? $inputData : func_get_args();
        $cnt = count($data);
        $result = array();
        foreach ($data[0] as $item) {
            $result[] = array($item);
        }
        for ($i = 1; $i < $cnt; $i++) {
            $result = combine_array($result, $data[$i]);
        }
        return $result;
    }
}

if (!function_exists('dika_string_recursion')) {
    /**
     * 数组笛卡尔积 返回字符串
     * @param $attrList
     * @param $res
     * @param $sep
     * @param $current
     * @return void
     */
    function dika_string_recursion($attrList, &$res, $sep = ':', $current = '')
    {
        if (empty($attrList)) {
            $res[] = ltrim($current, $sep);
            return;
        }
        $currentList = array_shift($attrList);
        foreach ($currentList as $attr) {
            dika_string_recursion($attrList, $res, $sep, $current . $sep . $attr);
        }
    }
}

if (!function_exists('memory_usage')) {
    /**
     * 输出当前内存用量
     * @return string
     */
    function memory_usage()
    {
        return (!function_exists('memory_get_usage')) ? '0' : round(memory_get_usage(true) / 1024 / 1024, 2) . 'MB';
    }
}

if (!function_exists('combine_array')) {
    /**
     * 两个数组的笛卡尔积
     * @param $arr1
     * @param $arr2
     * @return array
     */
    function combine_array($arr1, $arr2)
    {
        $result = array();
        foreach ($arr1 as $item1) {
            foreach ($arr2 as $item2) {
                $temp = $item1;
                $temp[] = $item2;
                $result[] = $temp;
            }
        }
        return $result;
    }
}


if (!function_exists('append_filter_param')) {
    /**
     * 追加过滤条件
     * @param $param
     * @param $currentModuleCode
     * @param array $conditions
     * @return array
     */
    function append_filter_param($param, $currentModuleCode, $conditions = [])
    {
        $isComplexFilter = false;
        if (!empty($param['filter']) !== false) {
            if (strpos(json_encode($param['filter']), '.')) {
                $isComplexFilter = true;
            }
        }

        if (!empty($param['fields'])) {
            if (strpos($param['fields'], '.') !== false) {
                $isComplexFilter = true;
            }
        }

        $newFilter = [];
        if ($isComplexFilter) {
            // 关联查询
            $appendFilter = [];
            foreach ($conditions as $field => $condition) {
                if ($field !== '_logic') {
                    $appendFilter["{$currentModuleCode}.{$field}"] = $condition;
                } else {
                    $appendFilter[$field] = $condition;
                }
            }

            if (!empty($param['filter'])) {
                $newFilter = [
                    $param['filter'],
                    $appendFilter,
                    "_logic" => "AND"
                ];
            } else {
                $newFilter = $appendFilter;
            }
        } else {
            // 非关联查询
            if (!empty($param['filter'])) {
                $newFilter = [
                    $param['filter'],
                    "_logic" => "AND"
                ];

                if (array_key_exists('_logic', $conditions) && $conditions['_logic'] === 'OR') {
                    $newFilter[] = $conditions;
                } else {
                    foreach ($conditions as $field => $condition) {
                        if ($field !== '_logic') {
                            $newFilter[$field] = $condition;
                        }
                    }
                }

            } else {
                $newFilter = $conditions;
            }
        }

        return $newFilter;

    }
}


if (!function_exists('number_floor_precision')) {
    /**
     * 取$precision位小数 向下取
     * @param $number
     * @param $precision
     * @return float|int
     */
    function number_floor_precision($number, $precision)
    {
        $steps = pow(10, (int)$precision);
        $numberUp = $number * $steps;
        $numberUp = floor($numberUp);
        return $numberUp / $steps;
    }
}

if (!function_exists('build_complex_query_fields')) {
    /**
     * 构建复杂查询字段
     * @param array $fields
     * @param string $sep 模块与字段的分隔符
     * @return array
     */
    function build_complex_query_fields(array $fields, $sep = "__")
    {
        $newFields = [];
        foreach ($fields as $key => &$field) {
            $explodeField = explode('.', $field);
            if (count($explodeField) > 1) {

                if (isset(Module::$moduleDictData['field_index_by_code'][$explodeField[0]])) {
                    $customFields = array_keys(Module::$moduleDictData['field_index_by_code'][$explodeField[0]]['custom'] ?? []);
                    if (in_array($explodeField[1], $customFields)) {
                        // 自定义字段 需要处理查询规则
                        $field = "JSON_UNQUOTE(JSON_EXTRACT(`{$explodeField[0]}`.`json`,'$.{$explodeField[1]}'))";
                    }
                }

                $newFields[] = "{$field} AS {$explodeField[0]}{$sep}{$explodeField[1]}";
            }
        }
        return $newFields;
    }
}

if (!function_exists('separate_complex_query_data')) {
    /**
     * 分离复杂查询的数据
     * @param $data
     * @param string $sep
     * @param string $mainTable
     * @return array
     */
    function separate_complex_query_data($data, $sep = "__", $mainTable = '')
    {
        $newData = [];
        foreach ($data as $key => $value) {
            $explodeField = explode($sep, $key);
            if (count($explodeField) > 1 && $explodeField[0] !== $mainTable) {
                $newData[$explodeField[0]][$explodeField[1]] = $value;
            } else if (count($explodeField) > 1 && $explodeField[0] === $mainTable) {
                $newData[$explodeField[1]] = $value;
            } else {
                $newData[$key] = $value;
            }
        }
        return $newData;
    }
}

if (!function_exists('auto_fill_tenant_id_with_data')) {
    /**
     * 自动填充租户ID
     * @param array $data
     * @param string $field
     * @return int
     */
    function auto_fill_tenant_id_with_data($data = [], $field = '')
    {
        if (!array_key_exists($field, $data)) {
            return \request()->getTenantId();
        } else {
            return $data[$field];
        }
    }
}

if (!function_exists('get_random_str')) {
    /**
     * 获得随机字符串
     * @param $length
     * @return string
     * @throws Exception
     */
    function get_random_str($length = 8)
    {
        $strMap = [
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
            'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
            's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        ];
        $result = [];
        $maxIndex = count($strMap) - 1;
        for ($index = 0; $index < $length; $index++) {
            $result[] = $strMap[random_int(0, $maxIndex)];
        }
        return implode('', $result);
    }
}

if (!function_exists('format_exception_info')) {
    /**
     * 格式化异常信息
     * @param $e
     * @return string
     */
    function format_exception_info($e): string
    {
        return sprintf("%s:%d  %s\r\n%s", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getTraceAsString());
    }
}

if (!function_exists('parse_filter_to_tp_where')) {
    /**
     * json filter 转换
     * @param $filter
     * @param $currentModule
     * @return array
     */
    function parse_filter_to_tp_where($filter, $currentModule)
    {
        $res = [];
        foreach ($filter as $filterKey => $filterItem) {
            if (is_numeric($filterKey)) {
                $res[$filterKey] = parse_filter_to_tp_where($filterItem, $currentModule);
            } elseif ($filterKey === '_logic') {
                $res[$filterKey] = $filterItem;
            } else {
                $moduleCode = $currentModule;
                if (strstr($filterKey, '.') !== false) {
                    $fieldData = explode('.', $filterKey);
                    $moduleCode = $fieldData[0];
                    $filterKey = $fieldData[1];
                }
                if (!isset(Module::$moduleDictData['field_index_by_code'][$moduleCode])) {
                    throw_strack_exception('unknown module ' . $moduleCode, ErrorCode::UNKNOWN_MODULE_CODE);
                }
                $fixedFields = array_keys(Module::$moduleDictData['field_index_by_code'][$moduleCode]['fixed'] ?? []);
                $customFields = array_keys(Module::$moduleDictData['field_index_by_code'][$moduleCode]['custom'] ?? []);
                if (in_array($filterKey, $fixedFields)) {
                    // 是固定字段那么吧currentModule拼接上字段名
                    $filterKey = $moduleCode . '.' . $filterKey;
                } else if (in_array($filterKey, $customFields)) {
                    $filterKey = "JSON_UNQUOTE(JSON_EXTRACT(`{$moduleCode}`.`json`,'$.{$filterKey}'))";
                } else {
                    throw_strack_exception('unknown column  ' . $filterKey . ' in ' . $moduleCode, ErrorCode::FIELD_NOT_FOUND);
                }
                $res[$filterKey] = $filterItem;
            }
        }
        return $res;
    }
}

if (!function_exists('transform_custom_field')) {
    /**
     *   转换 自定义字段
     * @param $field
     * @param $currentModuleCode
     * @param string $alias
     * @return array
     */
    function transform_custom_field($field, $currentModuleCode, $alias = '')
    {

        // key 是包含 . 的 那么就进行处理
        if (strstr($field, '.') !== false) {
            $fieldData = explode('.', $field);
            $moduleCode = $fieldData[0];
            $fieldName = $fieldData[1];
        } else {
            $moduleCode = $currentModuleCode;
            $fieldName = $field;
        }

        if (isset(Module::$moduleDictData['field_index_by_code'][$moduleCode])) {
            $customFields = array_keys(Module::$moduleDictData['field_index_by_code'][$moduleCode]['custom'] ?? []);
            if (in_array($fieldName, $customFields)) {
                // 自定义字段 需要处理查询规则
                if (!empty($alias)) {
                    $fieldName = "JSON_UNQUOTE(JSON_EXTRACT(`{$alias}`.`json`,'$.{$fieldName}'))";
                } else {
                    $fieldName = "JSON_UNQUOTE(JSON_EXTRACT(`{$moduleCode}`.`json`,'$.{$fieldName}'))";
                }
            } else {
                if (!empty($alias)) {
                    $fieldName = $alias . '.' . $fieldName;
                } else {
                    $fieldName = $moduleCode . '.' . $fieldName;
                }
            }
        } else {
            throw_strack_exception('unknown module ' . $moduleCode, ErrorCode::UNKNOWN_MODULE_CODE);
        }

        return $fieldName;
    }
}

if (!function_exists('rollback_parser_filter')) {
    /**
     * 处理过滤条件中的方法名
     * @param $data
     * @return mixed
     */
    function rollback_parser_filter($data)
    {
        if ((array_key_exists("param", $data) && array_key_exists("filter", $data['param'])) || array_key_exists("filter", $data)) {
            array_walk_recursive($data, 'rollback_parser_filter_condition');
        }
        return $data;
    }
}

if (!function_exists('rollback_parser_filter_condition')) {

    /**
     * 替换过滤条件中的方法名
     * @param $val
     * @param $key
     */
    function rollback_parser_filter_condition(&$val, $key)
    {
        $map = [
            'OR' => '-or',
            'AND' => '-and',
            'EQ' => '-eq',
            'NEQ' => '-neq',
            'GT' => '-gt',
            'EGT' => '-egt',
            'LT' => '-lt',
            'ELT' => '-elt',
            'LIKE' => '-lk',
            'NOTLIKE' => '-not-lk',
            'BETWEEN' => '-bw',
            'NOT BETWEEN' => '-not-bw',
            'IN' => '-in',
            'NOT IN' => '-not-in',
            'FIND_IN_SET' => '-fit',
        ];

        if (array_key_exists($val, $map)) {
            $val = $map[$val];
        }
    }
}

if (!function_exists('array_last')) {
    /**
     * Get the last element from an array.
     *
     * @param array $array
     * @return mixed
     */
    function array_last($array)
    {
        return end($array);
    }
}

if (!function_exists('transform_normal_order')) {
    /**
     * 转换复杂order条件
     * @param $order
     * @param $getModuleCode
     * @return array|mixed
     */
    function transform_normal_order($order, $getModuleCode)
    {
        if (!empty($order)) {
            if (is_array($order)) {
                $orderFields = $order;
            } else {
                $orderFields = explode(',', $order);
            }
            $order = [];
            foreach ($orderFields as $k => $v) {
                if (is_numeric($k)) {
                    $order[] = $v;
                } else {
                    $orderSortMethod = in_array(strtolower($v), ['asc', 'desc']) ? ' ' . $v : ' ASC';
                    $order[] = transform_custom_field($k, $getModuleCode) . $orderSortMethod;
                }
            }
        }
        return $order;
    }
}

if (!function_exists('array_index_by')) {
    /**
     * 使用多个key得到array_column的效果
     * @param array $data 数据
     * @param string $sep 分隔符
     * @param string ...$keys 用来组装key的键
     * @return array
     */
    function array_index_by(array &$data, $sep = '_', ...$keys)
    {
        $res = [];
        foreach ($data as &$item) {
            $aKeyValue = [];
            foreach ($keys as $key) {
                $aKeyValue[] = $item[$key];
            }
            $aKey = implode($sep, $aKeyValue);
            $res[$aKey] = &$item;
        }
        return $res;
    }
}

if (!function_exists('module_by_code')) {
    /**
     * 通过code获取module
     * @param $code
     * @param bool $throw
     * @return array
     */
    function module_by_code($code, $throw = true)
    {
        return Module::$moduleDictData['module_index_by_code'][$code] ?? [];
    }
}

if (!function_exists('module_by_id')) {
    /**
     * 通过id获取module
     * @param int $id
     * @param bool $throw
     * @return array
     */
    function module_by_id(int $id, $throw = true)
    {
        return Module::$moduleDictData['module_index_by_id'][$id] ?? [];
    }
}

if (!function_exists('build_update_json')) {
    /**
     * 生成
     * @param $field
     * @param $jsonData
     * @return string
     */
    function build_update_json($field, $jsonData)
    {
        $updateFields = '';
        if (empty($jsonData)) {
            throw new \common\exception\LogicException("update json data can`t be null", ErrorCode::UPDATE_JSON_FIELD_CANT_BE_NULL);
        }
        foreach ($jsonData as $k => $v) {
            if (empty($k)) {
                throw new \common\exception\LogicException("key can`t be null", ErrorCode::UPDATE_JSON_FIELD_CANT_BE_NULL);
            }
            if (is_array($v)) {
                throw new \common\exception\LogicException("value can`t be array", ErrorCode::UPDATE_JSON_VALUE_CANT_BE_NULL);
            }
            $updateFields .= ",'$.$k','$v'";
        }
        return sprintf("$field = JSON_SET(IFNULL($field,'{}')%s)", $updateFields);
    }
}

if (!function_exists('transform_custom_fields')) {
    /**
     *   转换 自定义字段查询
     * @param $fields
     * @param $currentModuleCode
     * @return array
     * @throws \support\exception\HttpResponseException
     */
    function transform_custom_fields($fields, $currentModuleCode)
    {
        foreach ($fields as &$field) {
            // key 是包含 . 的 那么就进行处理
            if (strstr($field, '.') !== false) {
                $fieldData = explode('.', $field);
                $moduleCode = $fieldData[0];
                $fieldName = $fieldData[1];
            } else {
                $moduleCode = $currentModuleCode;
                $fieldName = $field;
            }

            if (isset(Module::$moduleDictData['field_index_by_code'][$moduleCode])) {
                $customFields = array_keys(Module::$moduleDictData['field_index_by_code'][$moduleCode]['custom'] ?? []);
                if (in_array($fieldName, $customFields)) {
                    // 自定义字段 需要处理查询规则
                    $fieldName = "JSON_UNQUOTE(JSON_EXTRACT(`{$moduleCode}`.`json`,'$.{$fieldName}')) as $field";
                } else {
                    $fieldName = $moduleCode . '.' . $fieldName;
                }
            } else {
                throw_strack_exception('unknown module ' . $moduleCode, ErrorCode::UNKNOWN_MODULE_CODE);
            }
            $field = $fieldName;
        }

        return $fields;
    }
}

if (!function_exists('observer_subject_by_class_name')) {
    /**
     * 获得观察者对象
     * @param string $className
     * @return \teamones\dbeventObserver\interfaces\SplSubject
     * @throws \think\Exception
     */
    function observer_subject_by_class_name(string $className)
    {
        $res = model($className);
        if (!$res instanceof \teamones\dbeventObserver\interfaces\SplSubject) {
            throw new \common\exception\LogicException('class did`t implement splObserver interface', ErrorCode::OBSERVER_SUBJECT_INVALID);
        }
        return $res;
    }
}

if (!function_exists('build_queue_data_with_xu')) {
    /**
     * 生成一个队列数据 包含用户头信息
     * @param $data
     * @return false|string
     */
    function build_queue_data_with_xu($data)
    {
        if (!isset($data['xu'])) {
            $data['xu'] = request()->getXUserInfo();
        }
        return json_encode($data);
    }
}

if (!function_exists('validate_input_type')) {
    /**
     * 验证 输入类型
     * @param $validate
     * @param $data
     * @return array
     */
    function validate_input_type($validate, $data)
    {
        $validateTypePreg = ['number' => "\d", 'capital' => "A-Z", 'lower' => "a-z", 'special' => "\/|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\+|\{|\}|\:|\<|\>|\?|\[|\]|\,|\.|\/|\;|\'|\`|\-|\=|\\\|\|", 'chinese' => "\x7f-\xff+"];
        $res = [];
        $validationRules = ['number' => '数字', 'capital' => '大写字母', 'lower' => '小写字母', 'special' => '符号', 'chinese' => '中文'];
        $validateRulePreg = "";
        foreach ($validate as $validationRule) {
            $validateRulePreg .= $validateTypePreg[$validationRule];
            $res['preg'][] = $validationRule;
            $res['preg_match_rules'][] = $validationRules[$validationRule] . '格式';
        }
        $validateRulePreg = '/^[' . $validateRulePreg . ']+$/';
        $res['code'] = preg_match($validateRulePreg, $data);
        return $res;
    }
}

if (!function_exists('get_chat_entity_task_name')) {
    /**
     * 获取会话中的实体任务名
     * @param $entity
     * @param $task
     * @return string
     */
    function get_chat_entity_task_name($entity, $task = [])
    {
        $needModuleCode = ['shot', 'storyboard'];
        if (!empty($entity['module_id']) && in_array(module_by_id($entity['module_id'])['code'], $needModuleCode)) {
            return $entity['initial_episode_code'] . '/' . $entity['showings_number'] . '/' . $entity['name'] . ($task ? '/' . $task['name'] : '');
        } else {
            return $entity['name'] . ($task ? '/' . $task['name'] : '');
        }
    }
}

if (!function_exists('get_no_prefix_json_fields')) {
    /**
     * 解析json字符串 去掉code前缀
     * @param string $entityJsonCompressed
     * @param string $moduleCode
     * @return array
     */
    function get_no_prefix_json_fields(string $entityJsonCompressed, string $moduleCode)
    {
        $configArray = json_decode($entityJsonCompressed, true);
        $entityJson = [];
        foreach ($configArray as $fieldKey => $configArrayItem) {
            $entityJson[str_replace_once($moduleCode . '_', '', $fieldKey)] = $configArrayItem;
        }
        return $entityJson;
    }
}

if (!function_exists('teamones_request')) {

    /**
     * @param string $serviceName
     * @param string $route
     * @param $data
     * @param $headers
     * @param bool $autoXu
     * @param string $method
     * @return array|mixed|\Yurun\Util\YurunHttp\Http\Response
     */
    function teamones_request(string $serviceName, string $route, $data, $headers = [], bool $autoXu = true, string $method = 'POST')
    {
        $r = Request::connection();
        if ($autoXu) {
            $headers['X-Userinfo'] = request()->getXUserInfo();
        }
        $r->setMethod($method)
            ->setHeader($headers)
            ->setServerHost($serviceName)
            ->setRoute($route);
        if (isset($data)) {
            $r->setBody($data);
        }
        return $r->request();
    }
}

if (!function_exists('is_assoc')) {
    /**
     * 是否是关联数组 (一层)
     * @param $arr
     * @return bool
     */
    function is_assoc($arr)
    {
        $ci = 0;
        foreach ($arr as $ai => $av) {
            if ($ai !== $ci) {
                return true;
            }
            $ci++;
        }
        return false;
    }
}

if (!function_exists('decimal_data')) {
    /**
     * 保留小数点几位数
     * @param $data
     * @param int $format
     * @return float|int
     */
    function decimal_data($data, int $format = 2)
    {
        $format = pow(10, $format);
        return floor($data * $format) / $format;
    }
}

if (!function_exists('auto_fill_uuid')) {
    /**
     * 自动填充UUID
     * @param array $data
     * @param string $field
     * @return mixed
     * @throws \Exception
     */
    function auto_fill_uuid($data = [], $field = '')
    {
        if (empty($data[$field])) {
            return create_uuid();
        }
        return $data[$field];
    }
}

if (!function_exists('get_default_page')) {
    /**
     * 查询默认分页
     * @param $param
     * @return array
     */
    function get_default_page($param): array
    {
        if (empty($param['page'])) {
            return [1, C('database.database_max_select_rows')];
        }
        if ($param['page'][1] > C('database.database_max_select_rows')) {
            throw new \common\exception\LogicException('max query rows is ' . C('database.database_max_select_rows'), \support\ErrorCode::EXCEEDED_MAXIMUM_PAGE_NUM);
        }
        return $param['page'];
    }
}

if (!function_exists('get_month_day_list')) {
    /**
     * 获取年月日列表
     * @param int $startTime
     * @param int $endTime
     * @return array
     */
    function get_month_day_list(int $startTime, int $endTime): array
    {
        if ($endTime < $startTime) {
            $startTime ^= $endTime ^= $startTime ^= $endTime;
        }
        $startMonthDay = strtotime(date('Y-m-d', $startTime));  //开始日期 年-月
        $endMonthDay = strtotime(date('Y-m-d', $endTime));    //结束日期 年-月
        $currentMonthDay = $startMonthDay;

        $returnTimes = [];
        while ($currentMonthDay <= $endMonthDay) {
            $returnTimes[] = date('Y-m-d', $currentMonthDay);
            $currentMonthDay = strtotime(' + 1 day', $currentMonthDay);
        }
        return $returnTimes;
    }
}

if (!function_exists('split_array')) {
    /**
     * 将`int/string/array`统一成数组
     * @param mixed $paramVal
     * @param string $separator
     * @return array
     */
    function split_array($paramVal = [], string $separator = ','): array
    {
        if (!is_array($paramVal)) {
            if (empty($paramVal)) {
                return [];
            } else if (is_string($paramVal)) {
                return explode($separator, $paramVal);
            } else {
                return [$paramVal];
            }
        }
        return $paramVal;
    }
}

if (!function_exists('query_array_construct')) {
    /**
     * 构造请求数组
     * @param array $structure 构造数组结构
     * @param array $originArray 数据源
     * @return array
     */
    function query_array_construct(array $structure, array $originArray, array $defaultValue = null): array
    {
        $structure['_final'] = 'array_shift';
        $originArray = [$originArray];
        return callback_format_array($structure, $originArray, $defaultValue);
    }
}

if (!function_exists('result_array_construct')) {
    /**
     * 构造返回数组
     * @param array $structure 构造数组结构
     * @param array $originArray 数据源
     * @return array
     */
    function result_array_construct(array $structure, array $originArray, array $defaultValue = null): array
    {
        return callback_format_array($structure, $originArray, $defaultValue);
    }
}

if (!function_exists('callback_format_array')) {
    /**
     * 通过结构构造数组
     *
     * 结构内为 `key => callback` 键值对;
     * `callback`为空时对字段不做任何操作
     * `callback`支持传入闭包,
     * 支持`callbackA,param1,{{key}}...paramN|callbackB`,
     * 支持`\`（如`explode,\,`）,
     * 数组键值为`key`的数据将置于回调参数列表尾部;
     * `key`为`final`时支持对结果执行回调
     * @param array $structure 构造数组结构
     * @param array $originArray 数据源
     * @return array
     */
    function callback_format_array(array $structure, array $originArray, array $defaultValue = null): array
    {
        $res = [];
        // 目标格式为空时，返回原数组
        if (empty($structure)) {
            return $originArray;
        }
        // 拦截最终回调
        $finalCall = null;
        if (isset($structure['_final'])) {
            $finalCall = $structure['_final'];
            unset($structure['_final']);
        }
        // 各字段回调方法解析
        $callbackMap = [];
        foreach ($structure as $key => $callbackList) {
            if (is_callable($callbackList)) {
                $callbackList = [$callbackList];
            } else {
                $callbackList = explode_special($callbackList, '|');
            }
            foreach ($callbackList as $callbackRow) {
                if (is_callable($callbackRow)) {
                    $callback = $callbackRow;
                    $callbackRow = [];
                } else {
                    // 如果字段某回调带参
                    $callbackRow = explode_special($callbackRow, ',');
                    $callback = array_shift($callbackRow);
                }
                if (!isset($callbackMap[$key])) {
                    // 即使不是回调也写入，避免错误被忽略
                    $callbackMap[$key] = [];
                }
                $callbackMap[$key][] = [
                    'callback' => $callback,
                    'parameters' => $callbackRow
                ];
            }
        }
        foreach ($originArray as $itemKey => $item) {
            $temp = [];
            foreach ($callbackMap as $key => $callbackList) {
                if (!isset($temp[$key])) {
                    $temp[$key] = $item[$key] ?? ($defaultValue[$key] ?? null);
                }
                foreach ($callbackList as $callbackItem) {
                    // 替换回调参数中的{{key}}
                    $valueIndex = array_search('{{' . $key . '}}', $callbackItem['parameters']);
                    if ($valueIndex !== false) {
                        $callbackItem['parameters'] = array_replace($callbackItem['parameters'], [$valueIndex => $temp[$key]]);
                    } else {
                        $callbackItem['parameters'][] = $temp[$key];
                    }
                    $temp[$key] = empty($callbackItem['callback']) ? $temp[$key] : $callbackItem['callback'](...$callbackItem['parameters']);
                }
            }
            $res[$itemKey] = $temp;
        }
        // 对整个数组执行最终回调
        if (!empty($finalCall) && is_callable($finalCall)) {
            return $finalCall($res);
        }
        return $res;
    }
}

if (!function_exists('explode_special')) {
    /**
     * 带转义符的分割
     * @param string $data
     * @param string $separator
     * @param bool $keepSlash 保留分隔符转义
     * @return array
     */
    function explode_special(string $data, string $separator = ',', bool $keepSlash = false): array
    {
        $tempRow = explode($separator, $data);
        $res = [];
        while (!empty($tempRow)) {
            $item = array_shift($tempRow);
            $itemTemp = str_replace('\\\\', $separator, $item);
            if (strrpos($itemTemp, '\\') === strlen($itemTemp) - 1) {
                $item = substr($item, 0, strlen($item) - 1);
                $item .= ($keepSlash ? '\\' : '') . $separator;
                if (!empty($tempRow)) {
                    $item .= array_shift($tempRow);
                }
            }
            $res[] = $item;
        }
        return $res;
    }
}

if (!function_exists('arrayGroup')) {
    /**
     * 数组group by分组 ---- 自己写的，用之要验证下
     * @param array $list 数组
     * @param string $groupField group by key
     * @param string $concatField 连接的字段
     * @return array
     */
    function arrayGroup(array $list, string $groupField, string $concatField, string $otherField = '')
    {
        //数组重组
        $newList = [];
        foreach ($list as $val) {
            $newList[$val[$groupField]][] = $val;
        }

        $result = [];
        $keyList = array_unique(array_column($list, $groupField));
        //循环group key值
        foreach ($keyList as $keyVal) {
            $data = [];
            //需要连接的字段
            $concatList = explode(',', $concatField);
            foreach ($concatList as $concat) {
                $data[$concat] = implode(',', array_unique(array_column($newList[$keyVal], $concat)));
            }
            //不需要连接的字段
            if ($otherField) {
                $otherList = explode(',', $otherField);
                foreach ($otherList as $other) {
                    $data[$other] = $newList[$keyVal][0][$other];
                }
            }
            $data[$groupField] = $keyVal;
            $result[] = $data;
        }

        return $result;
    }
}

if (!function_exists('trim_time_range_end')) {
    /**
     * 处理查询时间范围，最晚查询时间不能超过今天 23:59:59
     * @param $timeRangeEnd
     * @return int
     */
    function trim_time_range_end($timeRangeEnd)
    {
        $todayEndTime = get_today_end_time();
        if ($timeRangeEnd > $todayEndTime) {
            $timeRangeEnd = $todayEndTime;
        }
        return (int)$timeRangeEnd;
    }
}

if (!function_exists('split_time_range')) {
    /**
     * 拆分时间范围，拆成历史和现在
     * @param $timeRange
     * @return array[]
     */
    function split_time_range($timeRange)
    {
        $res = [
            'history' => [],
            'today' => []
        ];
        if (count($timeRange) != 2) {
            return $res;
        }

        $todayStartTime = get_today_start_time();

        if ($timeRange[1] < $todayStartTime) {
            // 仅包含历史时间
            $res['history'] = $timeRange;
        } else {
            if ($timeRange[0] >= $todayStartTime) {
                // 仅包含今天时间
                $res['today'] = [
                    (int)$timeRange[0], trim_time_range_end($timeRange[1])
                ];
            } else {
                $res['history'] = [
                    (int)$timeRange[0], ($todayStartTime - 1)
                ];
                $res['today'] = [
                    $todayStartTime, trim_time_range_end($timeRange[1])
                ];
            }
        }

        return $res;
    }
}

if (!function_exists('get_today_start_time')) {
    /**
     * 获取今天开始的时间戳
     * @return false|int
     */
    function get_today_start_time()
    {
        return strtotime(date('Y-m-d 00:00:00'), time());
    }
}

if (!function_exists('get_today_end_time')) {
    /**
     * 获取今天结束的时间戳
     * @return false|int
     */
    function get_today_end_time()
    {
        return strtotime(date('Y-m-d 23:59:59'), time());
    }
}

if (!function_exists('check_time_range_max')) {
    /**
     * 限制时间范围只能最大取一年
     * @param $timeRange
     * @param $maxLength
     * @return void
     */
    function check_time_range_max($timeRange, $maxLength)
    {
        if (($timeRange[1] - $timeRange[0]) > $maxLength) {
            throw_strack_exception('Exceeded maximum time range', ErrorCode::EXCEEDEDMAXTIMERANGE);
        }
    }
}



